import { v2, Vec2 } from "cc";

// PlayerState.ts
export class PlayerState {
    public playerId: string = "";
    public position: Vec2 = v2(0, 0);
    public velocity: Vec2 = v2(0, 0);
    // public rotation: number = 0;
    public timestamp: number = 0;
    public sequence: number = 0;
    
    constructor(playerId?: string, position?: Vec2, velocity?: Vec2, rotation?: number) {
        if (playerId) this.playerId = playerId;
        if (position) this.position = position;
        if (velocity) this.velocity = velocity;
        // if (rotation !== undefined) this.rotation = rotation;
        this.timestamp = Date.now();
    }
    
    public clone(): PlayerState {
        const clone = new PlayerState();
        clone.playerId = this.playerId;
        clone.position = this.position.clone();
        clone.velocity = this.velocity.clone();
        // clone.rotation = this.rotation;
        clone.timestamp = this.timestamp;
        clone.sequence = this.sequence;
        return clone;
    }
    
    public serialize(): any {
        return {
            playerId: this.playerId,
            position: { x: this.position.x, y: this.position.y },
            velocity: { x: this.velocity.x, y: this.velocity.y },
            // rotation: this.rotation,
            timestamp: this.timestamp,
            sequence: this.sequence
        };
    }
    
    public static deserialize(data: any): PlayerState {
        const state = new PlayerState();
        state.playerId = data.playerId;
        state.position = v2(data.position.x, data.position.y);
        state.velocity = v2(data.velocity.x, data.velocity.y);
        // state.rotation = data.rotation;
        state.timestamp = data.timestamp;
        state.sequence = data.sequence;
        return state;
    }
}

// InputCommand.ts
export class InputCommand {
    public sequence: number;
    public direction: Vec2;
    //位置可选发送，后续优化
    public position: Vec2;
    public timestamp: number;
    
    constructor(sequence: number, direction: Vec2, position: Vec2, timestamp: number) {
        this.sequence = sequence;
        this.direction = direction;

        this.timestamp = timestamp;
        if(position){
            this.position = position;
        }

    }
    
    public serialize(): any {
        return {
            sequence: this.sequence,
            direction: { x: this.direction.x, y: this.direction.y },
            position: { x: this.position.x, y: this.position.y },
            timestamp: this.timestamp
        };
    }
    
    public static deserialize(data: any): InputCommand {
        return new InputCommand(
            data.sequence,
            v2(data.direction.x, data.direction.y),
            v2(data.position.x, data.position.y),
            data.timestamp
        );
    }
        // 检查输入是否重要（需要发送位置信息）
    public isSignificantChange(previousInput?: InputCommand): boolean {
        if (!previousInput) return true;
        
        // 方向变化超过45度
        const dot = this.direction.normalize().dot(previousInput.direction.normalize());
        if (dot < 0.7) return true;
        
        // 从静止到移动或从移动到静止
        const wasMoving = previousInput.direction.length() > 0.1;
        const isMoving = this.direction.length() > 0.1;
        if (wasMoving !== isMoving) return true;
        
        return false;
    }
}

// ServerPlayer.ts
export class ServerPlayer {
    public playerId: string;
    public position: Vec2;
    public velocity: Vec2 = v2(0, 0);
    public rotation: number = 0;
    public moveSpeed: number = 300;
    public maxSpeed: number = 400;
    public lastProcessedSequence: number = 0;
    public lastActivityTime: number = Date.now();
    
    constructor(playerId: string, position: Vec2) {
        this.playerId = playerId;
        this.position = position;
    }
    
    public getStateSnapshot(): PlayerState {
        return new PlayerState(
            this.playerId,
            this.position.clone(),
            this.velocity.clone(),
            this.rotation
        );
    }
}

// GameState.ts
export class GameState {
    public players: Map<string, PlayerState> = new Map();
    public timestamp: number = 0;
    public tickCount: number = 0;
    
    public serialize(): any {
        const playersObj: any = {};
        this.players.forEach((state, playerId) => {
            playersObj[playerId] = state.serialize();
        });
        
        return {
            players: playersObj,
            timestamp: this.timestamp,
            tickCount: this.tickCount
        };
    }
    
    public static deserialize(data: any): GameState {
        const gameState = new GameState();
        gameState.timestamp = data.timestamp;
        gameState.tickCount = data.tickCount;
        
        Object.keys(data.players).forEach(playerId => {
            gameState.players.set(playerId, PlayerState.deserialize(data.players[playerId]));
        });
        
        return gameState;
    }
}